package com.mine.androidTool;

import android.util.TypedValue;
import brut.androlib.res.decoder.AXmlResourceParser;
import com.google.common.collect.Maps;
import org.xmlpull.v1.XmlPullParser;

import java.io.IOException;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * 安卓apk包工具类
 * Created by xuchai on 2015/3/2.
 */
public class NewAndroidApkUtil {

    /**
     * 获取apk包的信息
     *
     * @param uri apk包的位置
     */
    public static void getApkInfo(String uri, ApkInfo info) {

        ZipFile zipFile = null;
        try {
            zipFile = new ZipFile(uri);
            ZipEntry entry = zipFile.getEntry("AndroidManifest.xml");
            AXmlResourceParser parser = new AXmlResourceParser();
            parser.open(zipFile.getInputStream(entry));
            while (true) {
                int type = parser.next();
                if (type == XmlPullParser.END_DOCUMENT) {
                    break;
                }
                switch (type) {
                    case XmlPullParser.START_TAG: {
                        for (int i = 0; i != parser.getAttributeCount(); ++i) {
                            if ("versionName".equals(parser.getAttributeName(i))) {
                                info.setVersionName(getAttributeValue(parser, i));
                            } else if ("package".equals(parser.getAttributeName(i))) {
                                info.setPackageName(getAttributeValue(parser, i));
                            } else if ("versionCode".equals(parser.getAttributeName(i))) {
                                info.setVersionCode(getAttributeValue(parser, i));
                            } else if ("minSdkVersion".equals(parser.getAttributeName(i))) {
                                String code = getAttributeValue(parser, i);
                                if (OSVersion.containsKey(code)) {
                                    info.setMinOsVersion(OSVersion.get(code));
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            info.setSuccess(false);
        } finally {
            if (zipFile != null) {
                try {
                    zipFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static final float[] RADIX_MULTS = {0.00390625F, 3.051758E-005F, 1.192093E-007F, 4.656613E-010F};

    private static final String DIMENSION_UNITS[] = {"px", "dip", "sp", "pt", "in", "mm", "", ""};

    private static final String FRACTION_UNITS[] = {"%", "%p", "", "", "", "", "", ""};

    private static String getAttributeValue(AXmlResourceParser parser, int index) {
        int type = parser.getAttributeValueType(index);
        int data = parser.getAttributeValueData(index);
        if (type == TypedValue.TYPE_STRING) {
            return parser.getAttributeValue(index);
        }
        if (type == TypedValue.TYPE_ATTRIBUTE) {
            return String.format("?%s%08X", getPackage(data), data);
        }
        if (type == TypedValue.TYPE_REFERENCE) {
            return String.format("@%s%08X", getPackage(data), data);
        }
        if (type == TypedValue.TYPE_FLOAT) {
            return String.valueOf(Float.intBitsToFloat(data));
        }
        if (type == TypedValue.TYPE_INT_HEX) {
            return String.format("0x%08X", data);
        }
        if (type == TypedValue.TYPE_INT_BOOLEAN) {
            return data != 0 ? "true" : "false";
        }
        if (type == TypedValue.TYPE_DIMENSION) {
            return Float.toString(complexToFloat(data)) +
                    DIMENSION_UNITS[data & TypedValue.COMPLEX_UNIT_MASK];
        }
        if (type == TypedValue.TYPE_FRACTION) {
            return Float.toString(complexToFloat(data)) +
                    FRACTION_UNITS[data & TypedValue.COMPLEX_UNIT_MASK];
        }
        if (type >= TypedValue.TYPE_FIRST_COLOR_INT && type <= TypedValue.TYPE_LAST_COLOR_INT) {
            return String.format("#%08X", data);
        }
        if (type >= TypedValue.TYPE_FIRST_INT && type <= TypedValue.TYPE_LAST_INT) {
            return String.valueOf(data);
        }
        return String.format("<0x%X, type 0x%02X>", data, type);
    }

    public static float complexToFloat(int complex) {
        return (float) (complex & 0xFFFFFF00) * RADIX_MULTS[(complex >> 4) & 3];
    }

    private static String getPackage(int id) {
        if (id >>> 24 == 1) {
            return "android:";
        }
        return "";
    }

    private static Map<String, String> OSVersion = Maps.newHashMap();

    static {
        OSVersion.put("3", "1.5");
        OSVersion.put("4", "1.6");
        OSVersion.put("5", "2.0");
        OSVersion.put("6", "2.0.1");
        OSVersion.put("7", "2.1");
        OSVersion.put("8", "2.2");
        OSVersion.put("9", "2.3");
        OSVersion.put("10", "2.3.3");
        OSVersion.put("11", "3.0");
        OSVersion.put("12", "3.1");
        OSVersion.put("13", "3.2");
        OSVersion.put("14", "4.0");
        OSVersion.put("15", "4.0.3");
        OSVersion.put("16", "4.1.1");
        OSVersion.put("17", "4.2");
        OSVersion.put("18", "4.3");
        OSVersion.put("19", "4.4");
        OSVersion.put("20", "4.4W");
        OSVersion.put("21", "5.0");
        OSVersion.put("22", "5.1");
        OSVersion.put("23", "6.0");
        OSVersion.put("24", "7.0");
        OSVersion.put("25", "7.1");
    }

}
